package com.user_service.filter;

import com.user_service.util.JwtUtil;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.security.SignatureException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Collections;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtUtil jwtUtil;

    public JwtAuthenticationFilter(JwtUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {

        String path = request.getServletPath();
        String method = request.getMethod();

        logger.info("JWT Filter processing: " + method + " " + path); // 添加日志

        // 跳过公开接口和OPTIONS预检请求
        if (shouldSkipAuth(request)) {
            logger.info("Skipping auth for: " + path);
            filterChain.doFilter(request, response);
            return;
        }

        String token = extractToken(request);
        if (token == null) {
            logger.warn("Missing token for path: " + path);
            sendErrorResponse(response, HttpStatus.UNAUTHORIZED, "Missing token");
            return;
        }

        try {
            // 先解析token获取用户ID，然后再验证
            Long userId = jwtUtil.getUserIdFromToken(token);
            if (jwtUtil.validateToken(token, userId)) {
                String username = jwtUtil.getUsernameFromToken(token);

                // 创建Authentication对象
                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(userId, null, Collections.emptyList());
                SecurityContextHolder.getContext().setAuthentication(authentication);

                logger.info("Authentication successful for user: " + userId);
            }
        } catch (ExpiredJwtException e) {
            logger.warn("Token expired for path: " + path);
            sendErrorResponse(response, HttpStatus.UNAUTHORIZED, "Token expired");
            return;
        } catch (UnsupportedJwtException | MalformedJwtException | SignatureException e) {
            logger.warn("Invalid token for path: " + path);
            sendErrorResponse(response, HttpStatus.UNAUTHORIZED, "Invalid token");
            return;
        } catch (Exception e) {
            logger.error("Token validation error for path: " + path, e);
            sendErrorResponse(response, HttpStatus.UNAUTHORIZED, "Token validation error");
            return;
        }

        filterChain.doFilter(request, response);
    }

    private boolean shouldSkipAuth(HttpServletRequest request) {
        String path = request.getServletPath();
        String method = request.getMethod();

        // 放行OPTIONS预检请求
        if ("OPTIONS".equalsIgnoreCase(method)) {
            return true;
        }

        // 支持多种路径格式
        return path.startsWith("/auth/register") ||
                path.startsWith("/api/auth/register") ||
                path.startsWith("/auth/login") ||
                path.startsWith("/api/auth/login") ||
                path.contains("/actuator/health") ||
                path.contains("/swagger") ||
                path.contains("/v3/api-docs") ||
                path.contains("/webjars");
    }

    private String extractToken(HttpServletRequest request) {
        String header = request.getHeader("Authorization");
        if (StringUtils.hasText(header) && header.startsWith("Bearer ")) {
            return header.substring(7);
        }
        return null;
    }

    private void sendErrorResponse(HttpServletResponse response, HttpStatus status, String message)
            throws IOException {
        response.setStatus(status.value());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);

        String jsonResponse = String.format(
                "{\"code\": %d, \"msg\": \"%s\"}",
                status.value(), message
        );

        response.getWriter().write(jsonResponse);
    }
}